package com.spring.cloud.commonsecurity.filter;

import com.alibaba.fastjson.JSON;
import com.spring.cloud.commonsecurity.tokenthread.TokenThreadLocal;
import com.spring.cloud.commonsecurity.vo.UserTokenBean;
import com.spring.cloud.commonsecurity.utils.DesCoderUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.StringUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.List;

public class TokenFilter extends BasicAuthenticationFilter {

    //秘钥
    private String secretKey = null;

    //构造方法,会调用父类方法
    public TokenFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }


    public void setSecretKey(String secretKey){
        this.secretKey = secretKey;
    }

    /**
     * 连接器方法
      * @param request  -- HTTP请求
     * @param response  --  Http响应
     * @param chain --  过滤器责任链
     * @throws IOException  --  IO异常
     * @throws ServletException --  Servlet异常
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        //从请求头(header)中提取token
        String token = request.getHeader("token");
        try{
            //token不为空
            if(!StringUtils.isEmpty(token)){
                //使用3DES工具类 解密token
                String tokenText = DesCoderUtils.decode3Des(secretKey,token);
                //转为java对象
                UserTokenBean userVo = JSON.parseObject(tokenText,UserTokenBean.class);
                //获取认证信息
                Authentication authentication = createAuthentication(userVo);
                //将token保持到线程变量中
                TokenThreadLocal.get().setToken(token);
                //设置认证信息,完成认证
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }finally {
            //执行下级过滤器
            chain.doFilter(request, response);
        }
    }

    /**
     *
     * @param userVo    -- token信息
     * @return
     */
    private Authentication createAuthentication(UserTokenBean userVo){
        //创建认证Principal对象
        Principal principal = ()->userVo.getUsername();
        //角色信息
        String roles = userVo.getRules();
        String[] rolesNames = (roles == null ? new String[0]:roles.split(","));
        List<GrantedAuthority> authorityList = new ArrayList<>();
        for(String rolesName: rolesNames){
            //创建授予权限信息的对象
            GrantedAuthority authority = new SimpleGrantedAuthority(rolesName);
            authorityList.add(authority);
        }
        //创建认证信息,它是Authentication 的实现类
        return new UsernamePasswordAuthenticationToken(principal,"",authorityList);

    }

}
